package com.otitan.forest.right.util;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.otitan.forest.right.constant.StaticConstant;
import com.otitan.webapp.framework.basepro.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @Description: 当前类作用描述
 * @Author: xiazw
 * @CreateDate: 2020/8/5 17:44
 */
@Slf4j
public class CommonUtil {

    // 加密
    private static final String NEC = "NEC";
    // 解密
    private static final String DEC = "DEC";
    // 智慧林业二期项目用户密码盐
    private static final String ZHLYEQ_SALT = "GYLYEQ";

    /**
     * 获取静态资源 绝对 路径
     *
     * @param []
     * @return java.lang.String
     * @throws
     * @author jiachangsen
     * @date 2020/08/12 13:57
     */
    public static String getStaticPath() {
        return Thread.currentThread().getContextClassLoader().getResource("").getPath();
    }

    /**
     * 从List<A> copy到List<B>
     *
     * @param list
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> copy(List<?> list, Class<T> clazz) {
        String oldOb = JSON.toJSONString(list);
        return JSON.parseArray(oldOb, clazz);
    }

    /**
     * 从对象A copy到 对象B
     *
     * @param ob    A
     * @param clazz B.class
     * @return B
     */
    public static <T> T copy(Object ob, Class<T> clazz) {
        String oldOb = JSON.toJSONString(ob);
        return JSON.parseObject(oldOb, clazz);
    }

    /**
     * 复制map对象
     *
     * @param paramsMap 被拷贝对象
     * @param resultMap 拷贝后的对象
     * @explain 将paramsMap中的键值对全部拷贝到resultMap中；
     * paramsMap中的内容不会影响到resultMap（深拷贝）
     */
    public static void mapCopy(Map paramsMap, Map resultMap) {
        if (resultMap == null) {
            resultMap = new HashMap();
        }
        if (paramsMap == null) {
            return;
        }

        Iterator it = paramsMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            Object key = entry.getKey();
            resultMap.put(key, paramsMap.get(key) != null ? paramsMap.get(key) : "");

        }
    }

    /**
     * 创建文件夹
     *
     * @param [bashPath]
     * @return java.lang.String
     * @throws
     * @author jiachangsen
     * @date 2020/08/12 14:41
     */
    public static String mkdirs(String bashPath) {
        Date date = new Date();
        String dateStr = DateUtil.parseDate(date, DateUtil.YYYYMMDD);

        // 文件相对路径
        String path = dateStr.substring(0, 4) + File.separator
                + dateStr.substring(0, 6) + File.separator
                + dateStr.substring(0, 8) + File.separator;

        String fileNewPath = bashPath + path;  //D:/forest-right-file/excel/
        File dir = new File(fileNewPath);     //2020\202011\20201107\

        boolean isSuccessMakeDir = false;
        if (!dir.exists()) {
            try {
                isSuccessMakeDir = dir.mkdirs();
                if (!isSuccessMakeDir) {
                    log.error("文件创建失败：{}" + path);
                    throw new BusinessException("创建文件夹失败！");
                }
            } catch (Exception e) {
                log.error("文件创建失败：{}" + path);
                throw new BusinessException("创建文件夹失败！");
            }
        }
        return fileNewPath;
    }


    public static String batchUploadFile(MultipartFile[] files, String bashPath) {
        // 创建文件夹
        String fileNewPath = mkdirs(bashPath);    //D:/forest-right-file/shp/2020\202011\20201107\
        fileNewPath = fileNewPath + File.separator + UUID.randomUUID().toString();
        File fileDir = new File(fileNewPath);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }

        String shpFileName = "";
        for (MultipartFile file : files) {
            try {
                String filename = file.getOriginalFilename();
                File file1 = new File(fileNewPath + File.separator + filename);
                file.transferTo(file1);

                if (filename.endsWith(StaticConstant.FILE_EXTENSION_SHP)) {
                    shpFileName = file1.getPath();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return shpFileName;

    }

    public static String uploadFile(String bashPath, MultipartFile file) {
        // 创建文件夹
        String fileNewPath = mkdirs(bashPath);

        try {
            String fileName = file.getOriginalFilename();
            String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
            UUID uuid = UUID.randomUUID();
            String fileNewName = uuid + fileSuffix;
            File dest = new File(fileNewPath + fileNewName);
            file.transferTo(dest);
            log.debug("【文件上传】文件路径：{}", dest.getPath());
            return dest.getPath();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("【文件失败】错误信息：{}", e.getMessage());
        }

        return null;
    }

    public static String uploadMdb(String bashPath, MultipartFile file) {
        // 创建文件夹
        String fileNewPath = mkdirs(bashPath);

        try {
            String fileName = file.getOriginalFilename();
            String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
            UUID uuid = UUID.randomUUID();
            String fileNewName = uuid + fileSuffix;
            File dest = new File(fileNewPath + fileNewName);
            file.transferTo(dest);
            log.debug("【文件上传】文件路径：{}", dest.getPath());
            return dest.getPath();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("【文件失败】错误信息：{}", e.getMessage());
        }

        return null;
    }

    /**
     * 实体对象转成Map
     *
     * @param obj 实体对象
     * @return
     */
    public static Map<String, Object> objectToMap(Object obj) {
        Map<String, Object> map = new HashMap<>();
        if (obj == null) {
            return map;
        }
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                map.put(field.getName(), field.get(obj));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    private static void closeStream(BufferedInputStream in, FileOutputStream out,
                                    BufferedOutputStream output) throws IOException {
        if (in != null) {
            in.close();
        }
        if (out != null) {
            out.close();
        }
        if (output != null) {
            output.close();
        }
    }

    /**
     * 智慧林业用户密码 加密 解密 处理
     *
     * @param exePath exe程序位置
     * @param type    操作方式：加密 nec   解密 dec
     * @param str     目标字符串
     * @param salt    盐
     * @return java.lang.StringBuffer
     * @throws
     * @author jiachangsen
     * @date 2020/09/02 19:13
     */
    public static String encryptAndDecode(String exePath, String type, String str, String salt) {
        StringBuffer sb = new StringBuffer();
        if (StrUtil.isEmpty(exePath) || StrUtil.isEmpty(type)
                || StrUtil.isEmpty(str) || StrUtil.isEmpty(salt)) {
            return sb.toString();
        }
        Process process = null;
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            String[] string = new String[]{exePath, type, str, salt};
            log.debug("【调用exe加密解密，参数】：{}", Arrays.toString(string));
            process = new ProcessBuilder(string).start();
            is = process.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (isr != null) {
                    isr.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }


    /**
     * 解密智慧林业用户密码
     * @author jiachangsen
     * @param [exePath, pwd]
     * @return java.lang.String
     * @exception
     * @date 2020/09/03 09:09
     */
    public static String decodePassword(String exePath, String pwd){
        return encryptAndDecode(exePath, DEC, pwd, ZHLYEQ_SALT);
    }

    /**
     * 将智慧林业二期用户密码转为当前系统用户密码
     * @author jiachangsen
     * @param [exePath, password]
     * @return java.lang.String
     * @exception
     * @date 2020/09/02 19:35
     */
    public static String zhlyPwdToNowPwd(String exePath, String password) {
        String pwd = encryptAndDecode(exePath, DEC, password, ZHLYEQ_SALT);
        if (StrUtil.isNotEmpty(pwd)){
            return new SimpleHash("MD5", pwd, StaticConstant.SALT, 1024).toHex();
        }
        return null;
    }


}
